package com.xishu.service.order.create;

import com.xishu.bo.PriceResult;
import com.xishu.bo.TicketResult;
import com.xishu.config.Constant;
import com.xishu.config.ContextConstant;
import com.xishu.entity.customer.CustomerTicket;
import com.xishu.entity.order.Order;
import com.xishu.entity.order.OrderItem;
import com.xishu.entity.order.TicketDiscountFee;
import com.xishu.entity.shop.DiscountTicket;
import com.xishu.entity.shop.Scene;
import com.xishu.entity.shop.SceneTimeConfig;
import com.xishu.response.ResponseStatus;
import com.xishu.service.CustomerService;
import com.xishu.service.DiscountTicketService;
import com.xishu.service.SceneService;
import com.xishu.service.order.base.OrderService;
import com.xishu.util.ClassUtil;
import com.xishu.util.ServletUtil;
import com.xishu.util.Tools;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.chain.impl.ChainBase;
import org.apache.commons.chain.impl.ContextBase;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

import static com.xishu.config.Constant.*;
import static com.xishu.response.ResponseStatus.*;

public class DiscountChain implements Tools {
    private static Logger logger = LoggerFactory.getLogger(DiscountChain.class);

    /**
     * 计算折扣价格
     *
     * @param order
     * @param price
     * @param priceResult
     * @return
     * @throws Exception
     */
    public Double calDiscountFee(Order order, double price, PriceResult priceResult) throws Exception {
        ChainBase chainBase = new ChainBase();
        Context context = new ContextBase();
        chainBase.addCommand(new InitClass());

        context.put(ContextConstant.CONTEXT_ORDER, order);
        context.put(ContextConstant.CUSTOMER_ID, order.getCustomerId());
        context.put(ContextConstant.PRICE_RESULT, priceResult);
        context.put(ContextConstant.PRICE, price);
        context.put(ContextConstant.CUT_COST, 0d);

        logger.info("the cal cut cost the price is {}", price);
        priceResult.setCostOrigin(price);

        logger.info("cal discount fee for order {}", order.getId());
        chainBase.addCommand(new InitClass());
        chainBase.addCommand(new CheckTicketValid());
        chainBase.addCommand(new FilterRightTicket());
        chainBase.addCommand(new TakeOutDiscount());
        chainBase.addCommand(new TicketDiscountFeeCmd());
        chainBase.execute(context);
        return getDouble((Double) context.get(ContextConstant.CUT_COST));
    }
}

class InitClass implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(InitClass.class);

    @Override
    public boolean execute(Context context) throws Exception {
        logger.info("init");
        Long customerId = (Long) context.get(ContextConstant.CUSTOMER_ID);
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        List<DiscountTicket> discountTicketList = new ArrayList<>();
        OrderService orderService = OrderService.getInstance();

        Long companyId = orderService.findCompanyId(order);
        context.put(ContextConstant.COMPANY_ID, companyId);

        Long userId = ServletUtil.getUserId();
        context.put(ContextConstant.USER_ID, userId);


        return false;
    }
}

/**
 * 校验优惠券是否可用
 */
class CheckTicketValid implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(CheckTicketValid.class);
    private SceneService sceneService = SceneService.getInstance();


    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        Long companyId = (Long) context.get(ContextConstant.COMPANY_ID);
        PriceResult priceResult = (PriceResult) context.get(ContextConstant.PRICE_RESULT);
        Long userId = (Long) context.get(ContextConstant.USER_ID);
        Long customerId = (Long) context.get(ContextConstant.CUSTOMER_ID);
        Double price = (Double) context.get(ContextConstant.PRICE);

        //是否已经成功添加了打折卷
        boolean addDiscountTicket = false;
        //只有一张优惠券可以使用
        boolean onlyOneTicketCanUse = false;
        //已经添加了一张优惠券
        boolean checkOneTicketAlready = false;
        Set<String> sameCodeList = new HashSet<>();

        List<DiscountTicket> discountTicketList = new ArrayList<>();
        context.put(ContextConstant.DISCOUNT_TICKET_LIST, discountTicketList);

        if (isEmpty(order.getTicketCodeList())) {
            logger.info("ticket code list is empty");
            return false;
        }

        for (String code : order.getTicketCodeList()) {
            DiscountTicket discountTicket = DiscountTicketService.getInstance().findTicketByCode(code, companyId);

            //优惠卷不存在
            if (discountTicket == null) {
                logger.info("{} do not find", code);
                priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_NOT_EXIST));
                continue;
            }

            Optional<CustomerTicket> customerTicketOptional = CustomerService.getInstance().findCustomerTicketInCompany(companyId, code);

            if (userId == null) {
                if (customerId == null) {
                    //匿名用户不能使用已经被绑定的CODE
                    if (customerTicketOptional.isPresent()) {
                        logger.info("{} bind by others", discountTicket.getCode());
                        priceResult.getResultList().add(new TicketResult(code, TICKET_EXCHANGE_BY_OTHERS));
                        continue;
                    }
                } else {
                    if (customerTicketOptional.isPresent()) {
                        //会员账号，不能使用被其它账号绑定的CODE
                        CustomerTicket customerTicket = customerTicketOptional.get();
                        boolean sameUser = equals(customerTicket.getCustomerId(), customerId);
                        if (!sameUser) {
                            logger.info("{} bind by others", discountTicket.getCode());
                            priceResult.getResultList().add(new TicketResult(code, TICKET_EXCHANGE_BY_OTHERS));
                            continue;
                        }
                    }
                }
            }

            //不是店长优惠券才需要判断（堂食，外卖），（商铺ID是否匹配），（有效期），（场景）,(是否已经使用)
            if (!DiscountTicketService.getInstance().isWaiterLeaderTicket(discountTicket)) {
                //优惠卷已使用
                if (getBoolean(discountTicket.getUsed())) {
                    logger.info("ticket used {}", discountTicket.getCode());
                    priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_NOT_EXIST));
                    continue;
                }

                //判断堂食是否可以使用
                List<Integer> tangShiList = Arrays.asList(ORDER_TYPE_QUICK_FOOD, ORDER_TYPE_TANG_SHI);
                Integer orderType = order.getOrderType();
                boolean tangShiOrder = tangShiList.stream().filter(p -> equals(p, orderType)).findAny().isPresent();
                if (tangShiOrder && !getBoolean(discountTicket.getTangshi())) {
                    logger.info("{} take out not match", discountTicket.getCode());
                    priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_FOR_TAKE_OUT));
                    continue;
                }

                //外卖订单，但是优惠券又不可以使用外卖
                if (!tangShiOrder && !getBoolean(discountTicket.getTakeout())) {
                    logger.info("{} tangshi not match", discountTicket.getCode());
                    priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_FOR_TANGSHI));
                    continue;
                }

                //优惠卷对应的商铺ID不匹配
                boolean shopMatch = discountTicket.getShopList().stream().anyMatch(p -> p.getId().longValue() == order.getShopId().longValue());
                if (!shopMatch) {
                    logger.info("{} shop do not match", discountTicket.getCode());
                    priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_NOT_EXIST));
                    continue;
                }

                //有效期要匹配上
                long currentTimeMillis = System.currentTimeMillis();
                if (!(currentTimeMillis >= discountTicket.getStartTime() && currentTimeMillis <= discountTicket.getEndTime())) {
                    priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_EXPIRED));
                    continue;
                }

                //时间要匹配上
                boolean timeMatch = discountTicket.getSceneList().stream().map(p -> {
                    try {
                        Scene scene = sceneService.findScene(p.getId());
                        return scene;
                    } catch (Exception e) {
                        logger.info("{} do not find", discountTicket.getCode());
                        logger.error("e", e);
                        priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_NOT_EXIST));
                        return null;
                    }
                }).anyMatch(p -> {
                    List<SceneTimeConfig> timeConfigList = p.getTimeConfigList();
                    return timeConfigList.stream().anyMatch(t -> sceneService.isMatchTimeConfig(t));
                });

                if (!timeMatch) {
                    logger.info("{} time not match", discountTicket.getCode());
                    priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_TIME_NOT_MATCH));
                    continue;
                }
            }

            //优惠卷的门槛要匹配上
            Double atLeastCost = getDouble(discountTicket.getAtLeastCost());
            if (price < atLeastCost) {
                logger.info("{} do not match the at least cost", discountTicket.getCode());
                priceResult.getResultList().add(new TicketResult(code, ResponseStatus.DISCOUNT_TICKET_NOT_MATCH_AT_LEAST_COST));
                continue;
            }

            //已经添加过了打折卷，又再次添加打折卷
            if (addDiscountTicket && getInt(discountTicket.getTicketType()) == DISCOUNT_TICKET_TYPE_DISCOUNT) {
                logger.info("{} has one discount ticket", discountTicket.getCode());
                priceResult.getResultList().add(new TicketResult(code, ResponseStatus.ONLY_ONE_DISCOUNT_TICKET));
                continue;
            }

            if (sameCodeList.contains(discountTicket.getCode())) {
                logger.info("{} same ticket in order", discountTicket.getCode());
                priceResult.getResultList().add(new TicketResult(discountTicket.getCode(), SAME_TICKET_IN_ONE_ORDER));
                continue;
            }

            //如果有相同的优惠卷，那么给提示
            sameCodeList.add(discountTicket.getCode());

            if (getInt(discountTicket.getTicketType()) == DISCOUNT_TICKET_TYPE_DISCOUNT) {
                addDiscountTicket = true;
            }

            //如果是菜品券，那么添加菜品券的判断
            if (getBoolean(discountTicket.getItemTicket())) {
                //判断该订单里面的菜是否在菜品券的范围里面
                List<Long> mainItemIdListInTicket = discountTicket.getMainItemIdList();
                List<Long> mainItemIdListInOrder = getMainItemIdListFromOrder(order);
                Collection intersection = CollectionUtils.intersection(mainItemIdListInTicket, mainItemIdListInOrder);

                if (isEmpty(intersection)) {
                    logger.info("{} order item not match", discountTicket.getCode());
                    priceResult.getResultList().add(new TicketResult(discountTicket.getCode(), ORDER_ITEM_NOT_MATCH_TICKET));
                    continue;
                }
            }

            if (onlyOneTicketCanUse) {
                logger.info("{} can not mutli used", discountTicket.getCode());
                priceResult.getResultList().add(new TicketResult(discountTicket.getCode(), ResponseStatus.DISCOUNT_TICKET_CAN_USE_ONCE));
                continue;
            }

            //已经添加了一张优惠券，新添加的优惠券不能多张使用
            if (checkOneTicketAlready && !getBoolean(discountTicket.getMultiUsed())) {
                logger.info("{} can not mutli used", discountTicket.getCode());
                priceResult.getResultList().add(new TicketResult(discountTicket.getCode(), ResponseStatus.DISCOUNT_TICKET_CAN_USE_ONCE));
                continue;
            }

            //已经成功添加了一张
            checkOneTicketAlready = true;

            if (!getBoolean(discountTicket.getMultiUsed())) {
                onlyOneTicketCanUse = true;
            }

            //条件满足的优惠卷
            discountTicketList.add(discountTicket);
        }

        if (isNotEmpty(discountTicketList)) {
            //如果存在只有一张才能使用的优惠卷，但是又有多张
            if (order.getTicketCodeList().size() > 1) {
                List<DiscountTicket> oneUsedTicketList = discountTicketList.stream().filter(p -> !getBoolean(p.getMultiUsed())).collect(Collectors.toList());
                for (DiscountTicket ticket : oneUsedTicketList) {
                    priceResult.getResultList().add(new TicketResult(ticket.getCode(), ResponseStatus.DISCOUNT_TICKET_CAN_USE_ONCE));
                    continue;
                }
            }
        }

        return false;
    }

    /**
     * 从一个订单里获取所有的主菜品ID，以方便菜品券做判断
     *
     * @param order
     * @return
     */
    public List<Long> getMainItemIdListFromOrder(Order order) {
        return getList(order.getOrderItemDetailList()).stream().map(orderItem -> {
            return orderItem.getMainItemId();
        }).collect(Collectors.toList());
    }
}

class FilterRightTicket implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(FilterRightTicket.class);

    @Override
    public boolean execute(Context context) throws Exception {
        PriceResult priceResult = (PriceResult) context.get(ContextConstant.PRICE_RESULT);
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        Long companyId = (Long) context.get(ContextConstant.COMPANY_ID);

        //resultList是上面添加的错误列表
        List<TicketResult> resultList = priceResult.getResultList();

        //过滤出没有问题的优惠卷，然后写计算价格，以及对应的描述
        if (isNotEmpty(order.getTicketCodeList())) {
            List<String> errorCodeList = resultList.stream().map(p -> p.getCode()).collect(Collectors.toList());

            List<String> rightCodeList = order.getTicketCodeList().stream().filter(p -> !errorCodeList.contains(p)).collect(Collectors.toList());
            for (String ticketCode : rightCodeList) {
                resultList.add(new TicketResult(ticketCode, DiscountTicketService.getInstance().findTicketByCode(ticketCode, companyId)));
            }

            //如果仅仅是相同的优惠卷，那么需要添加一个可用的进来
            Set<String> sameCodeListTmp = resultList.stream().filter(p -> equals(p.getStatus(), SAME_TICKET_IN_ONE_ORDER.getStatus())).map(p -> p.getCode()).collect(Collectors.toSet());
            for (String ticketCode : sameCodeListTmp) {
                resultList.add(new TicketResult(ticketCode, DiscountTicketService.getInstance().findTicketByCode(ticketCode, companyId)));
            }
        }

        List<TicketResult> rightTicketResult = priceResult.getResultList().stream().filter(p -> getInt(p.getStatus()) == 0).collect(Collectors.toList());

        context.put(ContextConstant.RIGHT_TICKET_RESULT, rightTicketResult);

        return false;
    }
}

class TakeOutDiscount implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(TakeOutDiscount.class);

    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        double cutCost = (Double) context.get(ContextConstant.CUT_COST);
        order.setTakeOutDiscountFee(null);

        if (getInt(order.getOrderType()) == ORDER_TYPE_TAKE_OUT) {
            OrderService orderService = OrderService.getInstance();
            Double takeOutOriginPrice = calTakeOutOriginFee(order);
            Long sceneId = orderService.getOrderSceneId(order);
            Scene scene = SceneService.getInstance().findScene(sceneId);
            if (scene != null) {
                //如果店铺设置了外卖打折，并且当前订单也是外卖单，那么打折
                Double takeoutFeePercent = scene.getTakeoutFeePercent();
                logger.info("will cut take out fee percent {}", takeoutFeePercent);

                //必须大于等于0
                if (getDouble(takeoutFeePercent) > 0) {
                    //7.5折，那么就是折扣0。25
                    double percent = (10 - takeoutFeePercent) / 10d;
                    logger.info("take out cut percent is {}", percent);
                    cutCost = showInteger(takeOutOriginPrice * percent);
                    logger.info("take out cut cost is {}", showDouble(cutCost));

                    if (cutCost <= 0) {
                        logger.info("reset the cut cost to 0");
                        cutCost = 0d;
                    }

                    order.setTakeOutDiscountFee(showInteger(cutCost));
                } else {
                    logger.info("some take out fee percent error");
                }
            }

            context.put(ContextConstant.CUT_COST, cutCost);
        }

        return false;
    }

    /**
     * 获取外卖订单里面的原始价格
     *
     * @param order
     * @return
     */
    private Double calTakeOutOriginFee(Order order) {
        List<OrderItem> orderItemList = getList(order.getOrderItemDetailList());

        return orderItemList.stream().filter(p -> {
            return !getBoolean(p.getExcludeTakeOutDiscount());
        }).mapToDouble(p -> p.getItemPrice() * p.getCount()).sum();
    }
}

class TicketDiscountFeeCmd implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(TicketDiscountFeeCmd.class);
    private OrderService orderService = OrderService.getInstance();

    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        List<TicketResult> rightTicketResult = (List<TicketResult>) context.get(ContextConstant.RIGHT_TICKET_RESULT);
        List<DiscountTicket> discountTicketList = (List<DiscountTicket>) context.get(ContextConstant.DISCOUNT_TICKET_LIST);
        double price = (Double) context.get(ContextConstant.PRICE);
        PriceResult priceResult = (PriceResult) context.get(ContextConstant.PRICE_RESULT);
        double cutCost = (Double) context.get(ContextConstant.CUT_COST);

        List<TicketDiscountFee> ticketDiscountFeeList = new ArrayList<>();
        OrderService orderService = OrderService.getInstance();

        Double discountFee = 0d;
        //如果优惠卷都没有问题，然后减去优惠卷的金额
        if (isNotEmpty(rightTicketResult)) {
            Order cloneOrder = (Order) ClassUtil.clone(order);

            List<String> codeList = rightTicketResult.stream().map(p -> p.getCode()).collect(Collectors.toList());
            //过滤出可用的优惠卷
            discountTicketList = discountTicketList.stream().filter(p -> codeList.contains(p.getCode())).collect(Collectors.toList());

            //求减去的金额的总和
            for (DiscountTicket ticket : discountTicketList) {
                //这里判断优惠卷是否满足门槛，小计优惠后再处理，如果不满足门槛，则添加到返回的列表里面，同时不优惠
                if (price < getDouble(ticket.getAtLeastCost())) {
                    List<TicketResult> ticketResults = priceResult.getResultList().stream().filter(p -> !equals(p.getCode(), ticket.getCode())).collect(Collectors.toList());
                    priceResult.setResultList(ticketResults);
                    priceResult.getResultList().add(new TicketResult(ticket.getCode(), ResponseStatus.DISCOUNT_TICKET_NOT_MATCH_AT_LEAST_COST));
                    continue;
                }

                //添加菜品券的处理
                if (getBoolean(ticket.getItemTicket())) {
                    //单个菜品有效
                    if (!getBoolean(ticket.getMultiItemValid())) {
                        List<OrderItem> filterOrderItemList = filterOrderItemInDiscount(cloneOrder, ticket);

                        //券对应的菜已经都打了折扣了
                        if (isEmpty(filterOrderItemList)) {
                            continue;
                        }

                        //最低价格的菜,最低价格的菜，减少的金额不能超过本身的价格
                        Long lowestPriceOrderItemId = filterLowestPriceOrderItem(filterOrderItemList);
                        OrderItem orderItem = orderService.filterOrderItemList(cloneOrder, lowestPriceOrderItemId);
                        Double itemTicketCutFee = 0d;

                        addOrderItemDiscount(orderItem, 1);

                        //免单券
                        if (getInt(ticket.getTicketType()) == DISCOUNT_TICKET_TYPE_FREE_ITEM) {
                            logger.info("item free ticket {}", orderItem.getBasePrice());
                            itemTicketCutFee = orderItem.getBasePrice();
                        } else if (getInt(ticket.getTicketType()) == Constant.DISCOUNT_TICKET_TYPE_CASH && getDouble(ticket.getDiscountCash()) > 0) {
                            //满减券
                            //菜的价格比减少的钱更小，以菜的价格为准
                            itemTicketCutFee = Math.min(getDouble(orderItem.getBasePrice()), ticket.getDiscountCash());
                        } else if (getInt(ticket.getTicketType()) == Constant.DISCOUNT_TICKET_TYPE_DISCOUNT && getDouble(ticket.getDiscount()) > 0) {
                            //折扣券
                            logger.info("discount ticket {}", orderItem);
                            itemTicketCutFee = orderItem.getBasePrice() * getDiscount(ticket);
                        }

                        //香港版本取整，美国版本取小数点后两位
                        itemTicketCutFee = showInteger(itemTicketCutFee).doubleValue();

                        //减去菜品的金额
                        discountFee = discountFee + itemTicketCutFee;
                        cutCost = cutCost + itemTicketCutFee;
                        price = price - itemTicketCutFee;
                        addTicketDiscountFeePrice(ticketDiscountFeeList, ticket.getCode(), itemTicketCutFee);
                    } else {
                        //多个菜品有效
                        //先过滤出相关的菜
                        List<OrderItem> filterOrderItemList = filterOrderItemInDiscount(cloneOrder, ticket);
                        Double itemTicketCutFee = 0d;

                        //免单券
                        if (getInt(ticket.getTicketType()) == DISCOUNT_TICKET_TYPE_FREE_ITEM) {
                            itemTicketCutFee = filterOrderItemList.stream().mapToDouble(orderItem -> orderItem.getBasePrice() * (orderItem.getCount() - orderItem.getDiscountNumber())).sum();
                        } else if (getInt(ticket.getTicketType()) == Constant.DISCOUNT_TICKET_TYPE_CASH && getDouble(ticket.getDiscountCash()) > 0) {
                            //满减券
                            //菜的价格比减少的钱更小，以菜的价格为准
                            double tmpCutFee = filterOrderItemList.stream().mapToDouble(orderItem -> {
                                return Math.min(ticket.getDiscountCash(), orderItem.getBasePrice()) * (orderItem.getCount() - orderItem.getDiscountNumber());
                            }).sum();

                            itemTicketCutFee = tmpCutFee;
                        } else if (getInt(ticket.getTicketType()) == Constant.DISCOUNT_TICKET_TYPE_DISCOUNT && getDouble(ticket.getDiscount()) > 0) {
                            //折扣券
                            itemTicketCutFee = filterOrderItemList.stream().mapToDouble(orderItem -> orderItem.getBasePrice() * (orderItem.getCount() - orderItem.getDiscountNumber())).sum() * getDiscount(ticket);
                        }

                        //设置折扣数量
                        for (OrderItem orderItem : filterOrderItemList) {
                            orderItem.setDiscountNumber(orderItem.getCount());
                        }

                        //香港版本取整，美国版本取小数点后两位
                        itemTicketCutFee = showInteger(itemTicketCutFee).doubleValue();

                        //减去菜品的金额
                        discountFee = discountFee + itemTicketCutFee;
                        cutCost = cutCost + itemTicketCutFee;
                        price = price - itemTicketCutFee;

                        addTicketDiscountFeePrice(ticketDiscountFeeList, ticket.getCode(), itemTicketCutFee);
                    }

                    continue;
                }

                if (getInt(ticket.getTicketType()) == Constant.DISCOUNT_TICKET_TYPE_DISCOUNT && getDouble(ticket.getDiscount()) > 0) {
                    logger.info("will cut discount {}", ticket.getDiscount());
                    Double itemDiscountPercent = calDiscountPercent(order);
                    double ticketDiscountFee = showInteger(price * (1 - ticket.getDiscount() / 10d) * itemDiscountPercent).doubleValue();
                    discountFee = discountFee + ticketDiscountFee;
                    cutCost = cutCost + ticketDiscountFee;
                    price = price - ticketDiscountFee;

                    addTicketDiscountFeePrice(ticketDiscountFeeList, ticket.getCode(), ticketDiscountFee);
                    continue;
                }

                if (getInt(ticket.getTicketType()) == Constant.DISCOUNT_TICKET_TYPE_CASH && getDouble(ticket.getDiscountCash()) > 0) {
                    logger.info("will cut cash {}", ticket.getDiscountCash());
                    Double discountCash = ticket.getDiscountCash();
                    discountCash = showInteger(discountCash).doubleValue();
                    discountFee = discountFee + discountCash;
                    cutCost = cutCost + discountCash;
                    price = price - discountCash;

                    addTicketDiscountFeePrice(ticketDiscountFeeList, ticket.getCode(), discountCash);
                    continue;
                }
            }

            order.setTicketDiscountFeeList(ticketDiscountFeeList);
            order.setDiscountFee(discountFee);
            context.put(ContextConstant.CUT_COST, cutCost);
        }
        return false;
    }

    /**
     * 过滤出满足菜品券的菜同，计算打折费用的时候
     *
     * @param order
     * @param discountTicket
     * @return
     */
    public List<OrderItem> filterOrderItemInDiscount(Order order, DiscountTicket discountTicket) {
        return getList(order.getOrderItemDetailList()).stream().filter(orderItem -> {
            return getList(discountTicket.getMainItemIdList()).contains(getLong(orderItem.getMainItemId()).longValue()) && orderItem.getDiscountNumber() < orderItem.getCount();
        }).collect(Collectors.toList());
    }

    /**
     * 从订单里面筛选出一个最低价格的菜出来
     *
     * @param orderItemList
     * @return
     */
    public Long filterLowestPriceOrderItem(List<OrderItem> orderItemList) {
        orderItemList.sort(Comparator.comparing(OrderItem::getBasePrice));
        return orderItemList.get(0).getId();
    }

    /**
     * 添加菜品的价格
     *
     * @param orderItem
     * @param addDiscountNumber
     */
    public void addOrderItemDiscount(OrderItem orderItem, int addDiscountNumber) {
        int discountNumber = orderItem.getDiscountNumber();
        orderItem.setDiscountNumber(discountNumber + addDiscountNumber);
    }

    /**
     * 獲取優惠券的折扣
     *
     * @return
     */
    public Double getDiscount(DiscountTicket discountTicket) {
        return 1 - discountTicket.getDiscount() / 10d;
    }

    /**
     * 添加优惠券的费用
     *
     * @param ticketDiscountFeeList
     * @param code
     * @param fee
     */
    public void addTicketDiscountFeePrice(List<TicketDiscountFee> ticketDiscountFeeList, String code, Double fee) {
        TicketDiscountFee ticketDiscountFee = orderService.filterTicketDiscountFee(ticketDiscountFeeList, code);
        fee = getDouble(ticketDiscountFee.getFee()) + fee;
        ticketDiscountFee.setFee(showMoneyDouble(fee));
    }

    /**
     * 计算打折比例
     * <p>
     * 如果有菜不参与打折，那么比例将会小于100%
     *
     * @param order
     * @return
     */
    private Double calDiscountPercent(Order order) {
        List<OrderItem> orderItemList = getList(order.getOrderItemDetailList());

        if (isEmpty(orderItemList)) {
            logger.info("order item list is empty");
            return 1.0;
        }

        double discountItemSumPrice = orderItemList.stream().filter(p -> {
            return !getBoolean(p.getExcludeDiscountTicket());
        }).mapToDouble(p -> p.getItemPrice() * p.getCount()).sum();

        if (discountItemSumPrice == 0) {
            logger.info("no order item satisfy discount ticket");
        }

        double orderItemSumPrice = orderItemList.stream().mapToDouble(p -> p.getItemPrice() * p.getCount()).sum();
        return discountItemSumPrice / orderItemSumPrice;
    }
}
